package core;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import core.QuestionPattern.Level;
import db.IQuestionsDb;

public class PQuestionGenerator extends QuestionGenerator {

	private static final String PATTERNSTABLENAME = "PPatterns";
	private final Random _random;
	public final Map<Integer,PatternUsage> patternUsageMap;	//	TODO CHANGE ACCESS TO PRIVATE

	public PQuestionGenerator(IQuestionsDb db, Random random){
		_random = random;
		patternUsageMap = new HashMap<Integer,PatternUsage>();
	}

	@Override
	public Question generateNewQuestion(IQuestionsDb db, Level level){
		DbPatternRow patternRow = db.getRandomPPatternForLevel(level);	//	Draw a random pattern for the given Level
		String randomSubject = String.valueOf(db.getRabdomSubject(patternRow.getSubject()));	//	get a random subject for the pattern
		String questionString = patternRow.getPattern().replaceAll("#", randomSubject);	//	replace # with actual value
		String correctAnswer = String.valueOf(db.getObjectOf(patternRow.getSubject(), randomSubject, patternRow.getInfoTableName(), 
												patternRow.getObject()));	//	get the answer to the question
		String[] wrongAnswers;	//	initialize an array for the wrong answers to the question

		if(patternRow.isObjectValueIsString())	//	if answer is of type string then get related but different string
			wrongAnswers = db.getRandomObjectsDifferentFrom(patternRow.getSubject(),correctAnswer, patternRow.getInfoTableName()
															, patternRow.getObject(), NUMBEROFWRONGANSWERS);
		else	//	else, answer is of type double, so generate 3 other values close to the correct value
			wrongAnswers = generateWrongNumericValuesAround(Double.valueOf(correctAnswer),_random, NUMBEROFWRONGANSWERS);

		//	add pattern info to map in order to update statistics in the DB at the end of the game
		patternUsageMap.put(patternRow.getPatternId(), new PatternUsage(patternRow.getPatternId()));

		//	return a new and complete question object
		return new Question(this, patternRow.getPatternId(), questionString, correctAnswer, wrongAnswers, _random);


	}


	private String[] generateWrongNumericValuesAround(double correctValue, Random random, int sizeOfOutput) {
		double factor;
		String[] output = new String[sizeOfOutput];
		for(int i=0; i < output.length; i++){
			do{
				factor = random.nextDouble();	//	return a value between 0.0 and 1.0 not included
			}	while (factor != 0.0 && factor != 1.0);
			if(factor <= 0.5)	//	wrong values should be close to correct value
				factor += 1;
			output[i] = String.valueOf(correctValue * factor);
		}

		return output;
	}

	/* (non-Javadoc)
	 * @see Core.QuestionGenerator#aQuestionHasBeenAnswered(int, boolean)
	 */
	@Override
	public void aQuestionHasBeenAnswered(int questionId, boolean correctly) {
		patternUsageMap.get(questionId).aQuestionHasBeenAnswered(correctly);

	}

	@Override
	public void updateQuestionsStatisticsInDb(IQuestionsDb db) {
		for(Entry<Integer, PatternUsage> entry : patternUsageMap.entrySet()) 
			db.updatePatternStatistics(PATTERNSTABLENAME, entry);
	}

}